package cn.golxen.blog.rabbitMQ.consumer;

import cn.golxen.blog.commons.rabbitVo.*;
import cn.golxen.blog.commons.utils.RabbitMQTemplate;
import cn.golxen.blog.mapper.CategoryMapper;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
@Component
public class CategoryConsumer {
    @Autowired
    CategoryMapper categoryMapper;
    @Autowired
    RedisTemplate<String,String> redisTemplate;

    @RabbitListener(queues = "CategoryQue")
    @RabbitHandler
    public void categoryHandler(RabbitMQTemplate rabbitMQTemplate){
        switch (rabbitMQTemplate.getType()){
            case "deleteRedisCategory":
                deleteRedisCategory();
                break;
            case "addRedisCategories":
                addRedisCategories((AddRedisCategoriesVo)rabbitMQTemplate);
                break;
            case "addRedisLabelByCategory" :
                addRedisLabelByCategory((AddRedisLabelByCategoryVo) rabbitMQTemplate);
                break;
            case "addRedisLabelAll":
                addRedisLabelAll((AddRedisLabelAllVo) rabbitMQTemplate);
                break;
            case "deleteRedisLabelSet":
                deleteRedisLabelSet((DeleteRedisLabelSetVo) rabbitMQTemplate);
                break;
            case "addRedisCountOfLabel":
                addRedisCountOfLabel((AddRedisCountOfLabelVo) rabbitMQTemplate);
                break;
            case "deleteRedisLabelCount":
                deleteRedisLabelCount((DeleteRedisLabelCountVo) rabbitMQTemplate);
                break;
            case "addRedisCountByCategoryOrLabel":
                addRedisCountByCategoryOrLabel((AddRedisCountByCategoryOrLabelVo)rabbitMQTemplate);
                break;

        }
    }

    private void addRedisCountByCategoryOrLabel(AddRedisCountByCategoryOrLabelVo rabbitMQTemplate) {
        redisTemplate.opsForValue().set(rabbitMQTemplate.getCategoryOrLabel()+"_count",rabbitMQTemplate.getCount(),3600,TimeUnit.SECONDS);
    }

    private void deleteRedisLabelCount(DeleteRedisLabelCountVo rabbitMQTemplate){
        Set<String> keySet= redisTemplate.keys("label:*:count_essay");
        RedisSerializer<String> serializer=redisTemplate.getStringSerializer();
        if (keySet!=null){
            redisTemplate.executePipelined((RedisCallback<String>) connection->{
                keySet.forEach((value)->{
                    connection.del(serializer.serialize(value));
                });
                return null;
            });
        }

    }

    private void addRedisCountOfLabel(AddRedisCountOfLabelVo rabbitMQTemplate) {
        redisTemplate.opsForValue().set("label:"+rabbitMQTemplate.getLabel()+":count_essay",rabbitMQTemplate.getCount(),3600,TimeUnit.SECONDS);
    }

    private void deleteRedisLabelSet(DeleteRedisLabelSetVo rabbitMQTemplate) {
        Set<String> set=new HashSet<>();
        set.add("label_all");
        set.add("category:"+rabbitMQTemplate.getCategory()+":label");
        set.add("label_count");
        redisTemplate.delete(set);
//        redisTemplate.delete("label_all");
//        redisTemplate.delete("category:"+rabbitMQTemplate.getCategory()+":label");
    }

    private void deleteRedisCategory(){
        redisTemplate.delete("categories");
        redisTemplate.delete("category_count");
    }

    private void addRedisCategories(AddRedisCategoriesVo addRedisCategoriesVo){
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        AtomicReference<Float> f= new AtomicReference<>((float) 1);
        redisTemplate.executePipelined((RedisCallback<String>) connection -> {
            addRedisCategoriesVo.getList().forEach((value)->{
                connection.zAdd(serializer.serialize("categories"), f.get(),serializer.serialize(value));
                f.getAndSet(f.get() + 1);
            });

            connection.expire(serializer.serialize("categories"),3600);
            return null;
        });
    }

    private void addRedisLabelByCategory(AddRedisLabelByCategoryVo addRedisLabelByCategoryVo){

        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        if (addRedisLabelByCategoryVo.getSet().isEmpty()) {
            redisTemplate.opsForSet().add("category:" + addRedisLabelByCategoryVo.getCategory() + ":label", "此类别无标签");
            redisTemplate.expire("category:" + addRedisLabelByCategoryVo.getCategory() + ":label",3600, TimeUnit.SECONDS);
            log.info("empty");
        }
        else {
            redisTemplate.executePipelined((RedisCallback<String>) connection->{
                addRedisLabelByCategoryVo.getSet().forEach((value)->{
                    String jsonObject= JSON.toJSONString(value);
                    connection.sAdd(serializer.serialize("category:"+addRedisLabelByCategoryVo.getCategory()+":label"), serializer.serialize(jsonObject));
                });
                connection.expire(serializer.serialize("category:"+addRedisLabelByCategoryVo.getCategory()+":label"),3600);
                return null;
            });
        }

    }

    private void addRedisLabelAll(AddRedisLabelAllVo addRedisLabelAllVo){
        RedisSerializer<String> serializer = redisTemplate.getStringSerializer();
        redisTemplate.executePipelined((RedisCallback<String>) connection->{
            addRedisLabelAllVo.getSet().forEach((value)->{
                String jsonObject= JSON.toJSONString(value);
                connection.sAdd(serializer.serialize("label_all"), serializer.serialize(jsonObject));
            });
            connection.expire(serializer.serialize("label_all"),3600);
            return null;
        });
    }

}
